
export const regExpHelper: RegExpHelper = {
    isNumber(str: string){
        return /^-?\d+(\.\d+)?$/.test(str)
    },
    isBoolean(str: string){
        return str === 'true' || str === 'false'
    },
    isLetter(str: string) {
        return /^[a-zA-Z]+$/.test(str)
    },
    isValidVariableName(str: string) {
        return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(str)
    }
}

export const typeConversion = (value: any, type?: 'string' | 'number' | 'float' | 'boolean') => {
    if(!value) return 'undefined'
    if(type === 'string'){
        return `"${value}"`
    }
    if(!regExpHelper.isNumber(value)){
        if(!regExpHelper.isBoolean(value)) {
            return `"${value}"`
        }
    }
    
    return value
}

export class Parser{
    list = new Map()

    start(json: any[], enterName = "Main"){
        const dataMap = new Map()
        const nodeMap = new Map()
        const mainNodes:any[] = []
        const codes:string[] = []
        for (let i = 0; i < json.length; i++) {
            nodeMap.set(json[i].uuid, json[i])
            if(json[i].ClassName === enterName) {
                mainNodes.push(json[i])
            }
        }

        for (let i = 0; i < mainNodes.length; i++) {
            const mainNode = mainNodes[i]
            codes.push( this.to( 
                this.createInfo(mainNode.uuid, "enter", 'enter'), 
                this.createInfo("0", "output", "output"),
                nodeMap, 
                dataMap
            ))
        }

        return codes
    }

    private createInfo(uuid:string, linkNodeName: string, mode: Mode ){
        return {
            uuid,
            name: linkNodeName,
            mode
        }
    }

    private to(to: any, from: any, nodeMap:Map<string, any>, dataMap:Map<string, any>){
        const node = nodeMap.get(to.uuid)
        const targetParserNode = this.list.get(node.ClassName)

        if(targetParserNode){
            const data = dataMap.get(node.uuid) || {}
            dataMap.set(node.uuid, data)
            return targetParserNode({
                node: node,
                data,
                mode: 'enter',
                from,
                to,
                currentNodeName: to.name,
                regExpHelper,
                typeConversion,
                toNode:(toNode: any, mode: Mode, defaultValue = '')=>{
                    if(!toNode) return defaultValue
                    return this.to(this.createInfo(toNode.uuid, toNode.name, mode), from, nodeMap, dataMap)
                },
                next: ([toNode]: any, defaultValue = '')=>{
                    if(!toNode) return defaultValue

                    const mode = toNode.index === 0 ? "output" : "enter"
                    return this.to(this.createInfo(toNode.uuid, toNode.name, mode), from, nodeMap, dataMap)
                }
            })
        }
        else {
            console.warn(`不存在节点转换：${node.ClassName}`)
        }
    }

    addParserFunction(name: any, fun?: (option: any) => string){
        if(typeof name === 'string' ) this.list.set(name, fun)
        else {
            Object.keys(name).forEach( k => {
                this.addParserFunction(k, name[k])
            })
        }
    }

    static getParserList (plugin: any){
        if(plugin.__parser) return plugin.__parser
        const list:any = {}

        plugin.modules.forEach((item: any)=>{
            for (const key in item.nodes) {
                if (Object.prototype.hasOwnProperty.call(item.nodes, key)) {
                    if(item.nodes[key].parser){
                        list[item.nodes[key].name] = item.nodes[key].parser
                    }
                }
            }
        })

        plugin.__parser = list
        return list
    }
}